﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Web.Script.Serialization;

namespace MyCommon
{
    /// <summary>
    /// 借助Udp收发对象  --郭旭东
    /// </summary>
    public class UdpClientHelper : IDisposable
    {
        #region 字段与属性

        UdpClient m_client = null;
        bool disposed = false;
        /// <summary>
        /// 主机名或IP的字符串表示形式
        /// </summary>
        public string RemoteHostName { get; set; }
        /// <summary>
        /// 端口号
        /// </summary>
        public int RemotePort { get; set; }
        /// <summary>
        /// 序列化对象所使用的自定义类型转换器
        /// </summary>
        public List<JavaScriptConverter> JavaScriptConverter { get; private set; }

        #endregion

        #region 构造函数
        /// <summary>
        /// 构造UdpClientHelper
        /// </summary>
        public UdpClientHelper()
        {
            m_client = new UdpClient();
            JavaScriptConverter = new List<JavaScriptConverter>();
        }
        /// <summary>
        /// 构造UdpClientHelper
        /// </summary>
        /// <param name="remoteHostName">远程主机名</param>
        /// <param name="remotePort">远程端口</param>
        public UdpClientHelper(string remoteHostName, int remotePort)
            : this()
        {
            RemoteHostName = remoteHostName;
            RemotePort = remotePort;
        }
        /// <summary>
        /// 构造UdpClientHelper
        /// </summary>
        /// <param name="localPort">本地端口</param>
        public UdpClientHelper(int localPort)
        {
            m_client = new UdpClient(localPort);
            JavaScriptConverter = new List<JavaScriptConverter>();
        }
        #endregion

        #region 方法
        /// <summary>
        /// 发送对象
        /// </summary>
        /// <param name="obj">要发送的对象</param>
        public void Send(Object obj)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("UdpClientHelper", "UdpClientHelper已经被释放");
            }
            try
            {
                m_client.Connect(RemoteHostName, RemotePort);
            }
            catch (Exception e)
            {
                throw new Exception("UDP建立远程主机异常", e);
            }
            var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
            if (JavaScriptConverter.Any())
            {
                ser.RegisterConverters(JavaScriptConverter);
            }
            string str;
            try
            {
                str = ser.Serialize(obj);
            }
            catch (Exception e)
            {
                throw new Exception("UDP发送数据前序列化对象异常", e);
            }
            var array = Encoding.UTF8.GetBytes(str);
            int length;
            try
            {
                length = m_client.Send(array, array.Length);
            }
            catch (Exception e)
            {
                throw new Exception("UDP发送异常", e);
            }
            if (length != array.Length)
            {
                throw new Exception("UDP发送数据不完整");
            }
        }
        /// <summary>
        /// 接收对象
        /// </summary>
        /// <typeparam name="TResult">接收到对象的类型</typeparam>
        /// <param name="remoteEP">远程的终结点</param>
        /// <returns>接收到的对象</returns>
        public TResult Receive<TResult>(ref IPEndPoint remoteEP)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("UdpClientHelper", "UdpClientHelper已经被释放");
            }
            byte[] array;
            try
            {
                array = m_client.Receive(ref remoteEP);
            }
            catch (Exception e)
            {
                throw new Exception("UDP接收异常", e);
            }
            var str = Encoding.UTF8.GetString(array);
            var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
            if (JavaScriptConverter.Any())
            {
                ser.RegisterConverters(JavaScriptConverter);
            }
            TResult obj;
            try
            {
                obj = ser.Deserialize<TResult>(str);
            }
            catch (Exception e)
            {
                throw new Exception("UDP发送数据前序列化对象异常", e);
            }
            return obj;
        }

        #endregion

        #region 释放资源相关
        /// <summary>
        /// 关闭对象并释放资源
        /// </summary>
        public void Close()
        {
            Dispose();
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing">是否释放托管资源</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }
            if (disposing)
            {
                if (m_client != null)
                {
                    m_client.Close();
                    m_client = null;
                }
            }
            disposed = true;
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// 终结对象
        /// </summary>
        ~UdpClientHelper()
        {
            Dispose(false);
        }

        #endregion

    }
}
